﻿using AutoMapper;
using MD5Hash;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Linq.Expressions;
using System.Security.Claims;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Workflow2211A.Application.DTO;
using Workflow2211A.Application.DTO.Inputs;
using Workflow2211A.Application.DTO.Outputs;
using Workflow2211A.Domain;
using Workflow2211A.Domain.Entities;

namespace Workflow2211A.Application.Services
{
    /// <summary>
    /// 用户实现--登录
    /// </summary>
    public class UserService:IUserService
    {
        /// <summary>
        /// 用户仓储
        /// </summary>
        private readonly IBaseRepository<UserModel> _userRepository;
        /// <summary>
        /// AutoMapper
        /// </summary>
        private readonly IMapper _mapper;

        private readonly IConfiguration _config;

        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="userRepository">用户仓储</param>
        /// <param name="mapper">AutoMapper</param>
        public UserService(IBaseRepository<UserModel> userRepository,IMapper mapper, IConfiguration configuration)
        {
            _userRepository = userRepository;
            _mapper = mapper;
            _config = configuration;
        }
        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="input">输入参数</param>
        /// <returns>返回用户信息</returns>
        public APIResult<UserOutput> Login(UserLoginInput input)
        {
            //通过手机号/邮箱/账号+密码登录(Expression)
            var pwd = input.UserPass.GetMD5();
            //默认情况下用账号加密码登录【表达式树】
            Expression<Func<UserModel,bool>> exp = user=>user.UserName == input.UserName
            && user.UserPass == pwd;
            //判断UserName是否是手机号(正则)
            //Regex.IsMatch 是 C# 中用于正则表达式匹配的核心方法，
            //它的作用是检查一个字符串是否符合指定的正则表达式模式
            var phone = @"^1[3-9]\d{9}$";
            if (Regex.IsMatch(input.UserName, phone))
            {
                exp = user => user.Phone == input.UserName && user.UserPass == pwd;
            }
            //判断UserName是否是邮箱(正则)
            var email = @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*";
            if (Regex.IsMatch(input.UserName, email))
            {
                exp = user => user.Email == input.UserName && user.UserPass == pwd;
            }

            var user = _userRepository.GetAll().AsTracking()
                .Include(x=>x.Role)
                .FirstOrDefault(exp);

            if (user == null)
            {
                return new APIResult<UserOutput>
                {
                    Code =ResultCode.Fail,
                    Message ="用户名或者密码错误",
                };
            }

            var userDto = _mapper.Map<UserOutput>(user);
            userDto.RoleName = user.Role.RoleName;
            userDto.Token = GenerateJwtToken(userDto);

            return new APIResult<UserOutput>
            {
                Code = ResultCode.Success,
                Message = "登录成功",
                Data = userDto
            };
        }
        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <returns></returns>
        public List<UserOutput> GetUser()
        {
            var user = _userRepository.GetAll().AsNoTracking().Include(x => x.Role).Take(4);
            var userDto = _mapper.Map<List<UserOutput>>(user);
            return userDto;
        }

        /// <summary>
        /// 生成JWT令牌
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public string GenerateJwtToken(UserOutput user)
        {
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["JwtSettings:SecretKey"]));
            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

            //jwt中的Playload(一般放的是用户信息)
            //Head中：算法类型

            var claims = new[]
            {
                new Claim("UserName", user.UserName),
                new Claim("NickName", user.NickName),
                new Claim("UserId", user.Id.ToString()),
                new Claim("RoleId", user.RoleId.ToString()),
                new Claim("RoleName", user.RoleName)
            };

            var token = new JwtSecurityToken(
                issuer: _config["JwtSettings:Issuer"],
                audience: _config["JwtSettings:Audience"],
                claims: claims,
                expires: DateTime.Now.AddMinutes(120),
                signingCredentials: credentials
            );

            return new JwtSecurityTokenHandler().WriteToken(token);
        }
    }
}
